package com.jy.modules.cims.api;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.jy.modules.cims.common.CimsConstant;
import com.jy.modules.cims.common.JResult;
import com.jy.modules.cims.common.open.api.JieYueApiHelper;
import com.jy.modules.cims.common.open.api.dto.EntryParameter;
import com.jy.modules.cims.common.open.api.dto.ResponseContent;
import com.jy.modules.cims.common.open.api.enums.EntryResponseEnum;
import com.jy.modules.cims.common.sysUtils.DateTimeUtils;
import com.jy.modules.cims.component.api.InteractClassInvokeEnum;
import com.jy.modules.cims.component.sysAssist.JieYueApiAssist;
import com.jy.modules.cims.data.dto.InteractClassInvokeDto;
import com.jy.modules.cims.data.dto.InteractClassParamterDto;
import com.jy.modules.cims.data.interact.api.JieYueMessage;
import com.jy.modules.cims.data.interact.api.ResponseMessageEnum;
import com.jy.modules.cims.data.interact.tbj.loan.response.ResponseDataEnum;
import com.jy.modules.cims.interact.InteractClassInvokeService;
import com.jy.modules.platform.sysconfig.service.SysConfigService;

/**
 * @classname JieYueApiController
 * @description 定义对外围系统发布的服务的控制层
 * @author shengzhoutao
 * @date 2015-11-10
 */
@Controller
@RequestMapping(value = "/api/mm/jieyue")
public class JieYueApiController {
	private static Logger logger = LoggerFactory.getLogger(JieYueApiController.class);

	@Autowired
	@Qualifier("com.jy.modules.platform.sysconfig.service.SysConfigService")
	private SysConfigService sysConfigService;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.component.sysAssist.JieYueApiAssist")
	private JieYueApiAssist jieYueApiAssist;

	@Autowired
	@Qualifier("com.jy.modules.cims.interact.InteractClassInvokeService")
	private InteractClassInvokeService interactClassInvokeService;

	/**
	 * @description 对商户提供的服务处理
	 * @param parameter
	 *            接收参数实体对象
	 * @return ResponseContent 处理返回实体对象
	 * @author shengzhoutao
	 * @date 2016-11-10
	 */
	@RequestMapping(value = "/2016/v1", method = RequestMethod.POST)
	@ResponseBody
	public ResponseContent doWork(EntryParameter parameter) {
		logger.info("==============接受商户请求, 处理服务==============");

		ResponseContent responseContent = null;
		try {
			// 验证输入公共参数
			JResult validateResult = validateEntryParameter(parameter);
			if (!validateResult.isSuccess()) {
				responseContent = (ResponseContent) validateResult.getObj();
				return responseContent;
			}

			Map<String, Object> map = validateResult.getMap();
			String cooperorgCode = (String) map.get("cooperorgCode");
			InteractClassInvokeEnum interactClassInvokeConfig = (InteractClassInvokeEnum) map.get("interactClassInvokeConfig");

			Object responseData = new Object();
			responseContent = new ResponseContent(EntryResponseEnum.SUCESS21001);

			JieYueApiHelper helper = jieYueApiAssist.getJieYueApiHelperByCooperorgCode(cooperorgCode);

			Class<?> paramterClass = null;
			String errorMessage = "";
			try {
				paramterClass = Class.forName(interactClassInvokeConfig.getParamterName());
			} catch (ClassNotFoundException e) {
				logger.error("异常 ：", e);
				errorMessage = e.getMessage();
			}

			if (null != paramterClass) {
				Object dto = helper.parseData(parameter, paramterClass);

				// 验证接收请求内容信息(业务信息)
				errorMessage = jieYueApiAssist.validate(dto);
				if (StringUtils.hasText(errorMessage)) {
					responseContent = new ResponseContent(EntryResponseEnum.FAILURE41003);
					responseContent.setMessage(responseContent.getMessage() + "[" + errorMessage + "]");
				}
				// 验证接收信息通过
				else {
					responseData = doInvoke(interactClassInvokeConfig, dto);
				}
			} else {// 校验不通过
				responseContent = new ResponseContent(EntryResponseEnum.FAILURE41003);
				responseContent.setMessage(responseContent.getMessage() + "[" + errorMessage + "]");
			}

			responseContent.setMethod(parameter.getMethod());
			responseContent.setSign(parameter.getSign());
			helper.assembleResponse(responseContent, responseData);

			logger.info("处理结果，返回响应：" + responseContent);
			return responseContent;
		} catch (Exception e) {
			logger.error("异常 ：", e);
			responseContent = new ResponseContent(EntryResponseEnum.FAILURE41002);
			responseContent.setMessage(responseContent.getMessage() + "[" + e.getMessage() + "]");

			return responseContent;
		}
	}

	/**
	 * @description 验证参数
	 * @param parameter
	 *            参数实体对象
	 * @return result JResult
	 */
	private JResult validateEntryParameter(EntryParameter parameter) {
		JResult result = new JResult();
		result.setSuccess(false);

		ResponseContent responseContent = null;

		// 没有收到参数
		if (null == parameter) {
			responseContent = new ResponseContent(EntryResponseEnum.FAILURE41009);
			logger.info("处理结果，返回响应：" + responseContent);

			result.setObj(responseContent);
			return result;
		}

		logger.info("接受参数：" + JSON.toJSONString(parameter));
		String errorMessage = jieYueApiAssist.validate(parameter);
		if (StringUtils.hasText(errorMessage)) {
			responseContent = new ResponseContent(EntryResponseEnum.FAILURE41003);
			responseContent.setMessage(responseContent.getMessage() + "[" + errorMessage + "]");
			
			result.setObj(responseContent);
			return result;
		}
		
		// 验证请求时间
		String timestamp = parameter.getTimestamp();
		try {
			boolean vRTFlag = validateReceiveTimestamp(timestamp);
			if (!vRTFlag) {
				responseContent = new ResponseContent(EntryResponseEnum.FAILURE41007);
				String currentDateTime = DateTimeUtils.formatDate(new Date(), DateTimeUtils.DEFAULT_DATE_TIME_FORMAT);
				responseContent.setMessage(java.text.MessageFormat.format("客户端请求时间[{0}]和服务端时间[{1}]误差超过10分钟。", new Object[] { timestamp, currentDateTime }));
				logger.info("处理结果，返回响应：" + responseContent);

				result.setObj(responseContent);
				return result;
			}
		} catch (ParseException e) {
			responseContent = new ResponseContent(EntryResponseEnum.FAILURE41003);
			responseContent.setMessage(java.text.MessageFormat.format("客户端请求时间[{0}]不正确。", new Object[] { timestamp }));
			logger.info("处理结果，返回响应：" + responseContent);

			result.setObj(responseContent);
			return result;
		}

		// 验证商户
		String cooperorgCode = jieYueApiAssist.getCooperorgCodeByAppId(parameter.getAppId());
		if (null == cooperorgCode) {
			responseContent = new ResponseContent(EntryResponseEnum.FAILURE41004);
			logger.info("处理结果，返回响应：" + responseContent);

			result.setObj(responseContent);
			return result;
		}

		// 验证签名
		boolean success = jieYueApiAssist.checkSignByCooperorgCode(parameter, cooperorgCode);
		if (!success) {
			responseContent = new ResponseContent(EntryResponseEnum.FAILURE41001);
			logger.info("处理结果，返回响应：" + responseContent);

			result.setObj(responseContent);
			return result;
		}

		// 验证方法名
		String method = parameter.getMethod();
		logger.info("请求服务方法英文名称：" + method);
		InteractClassInvokeEnum interactClassInvokeConfig = InteractClassInvokeEnum.getInteractClassInvokeEnumByInterfaceMark(method);
		if (null == interactClassInvokeConfig) {// API接口名称取值不正确
			responseContent = new ResponseContent(EntryResponseEnum.FAILURE41003);
			responseContent.setMessage(java.text.MessageFormat.format("API接口名称[{0}]取值不正确。", new Object[] { method }));
			responseContent.setMethod(parameter.getMethod());

			result.setObj(responseContent);
			return result;
		}
		logger.info("请求服务方法中文描述：" + interactClassInvokeConfig.getDescription());
		
		Map<String, Object> returnMap = new HashMap<String, Object>();
		returnMap.put("cooperorgCode", cooperorgCode);
		returnMap.put("interactClassInvokeConfig", interactClassInvokeConfig);
		result.setMap(returnMap);

		result.setSuccess(true);
		return result;
	}

	/**
	 * @description 解析执行接口信息,通过反射调用方法
	 * @param interactClassInvokeConfig
	 * @param dto
	 * @return 执行接口返回结果。如果接口没有返回值，返回将是空；如果接口有返回非空值，返回有值，需要此值需要值做转换。
	 * @author shengzhoutao
	 * @date 2016-11-10
	 */
	private Object doInvoke(InteractClassInvokeEnum interactClassInvokeConfig, Object dto) {
		try {
			String parameterValue = JSON.toJSONString(dto);

			InteractClassInvokeDto interactClassInvokeDto = new InteractClassInvokeDto();
			interactClassInvokeDto.setClassName(interactClassInvokeConfig.getClassName());
			interactClassInvokeDto.setMethodName(interactClassInvokeConfig.getMethodName());

			List<InteractClassParamterDto> interactClassParamterList = new ArrayList<InteractClassParamterDto>();
			InteractClassParamterDto interactClassParamterDto = new InteractClassParamterDto();
			interactClassParamterDto.setParameterName(interactClassInvokeConfig.getParamterName());
			interactClassParamterDto.setParameterValue(parameterValue);
			interactClassParamterList.add(interactClassParamterDto);
			interactClassInvokeDto.setInteractClassParamterList(interactClassParamterList);

			Object responseData = interactClassInvokeService.doInvoke(interactClassInvokeDto);

			return responseData;
		} catch (Exception e) {
			logger.error("异常 ：", e);

			JieYueMessage responseMessage = new JieYueMessage();
			responseMessage.setId("");
			responseMessage.setResult(ResponseMessageEnum.FAILURE.getResult());
			responseMessage.setMessage(ResponseDataEnum.FAILURE.getMessage() + "[" + e.getMessage() + "]");
			return responseMessage;
		}
	}

	/**
	 * @description 验证接收时间戳
	 * @param receiveTimestamp
	 * @return true: 验证通过; false:验证不通过
	 * @throws ParseException
	 * @author shengzhoutao
	 * @date 2016-11-10
	 */
	private boolean validateReceiveTimestamp(String receiveTimestamp) throws ParseException {
		String vRTFlag = "";
		try {
			vRTFlag = sysConfigService.queryValueByCode("VALIDATE_RECEIVE_TIMESTAMP");
		} catch (Exception e) {
			logger.error("异常 ：", e);
		}
		
		if (vRTFlag.equalsIgnoreCase(CimsConstant.FLAG_NO)) {
			return true;
		}
		
		String end = DateTimeUtils.calDateStr(10, DateTimeUtils.DEFAULT_DATE_TIME_FORMAT);
		String begin = DateTimeUtils.calDateStr(-10, DateTimeUtils.DEFAULT_DATE_TIME_FORMAT);

		boolean vBegin = DateTimeUtils.dateCompare(receiveTimestamp, begin, DateTimeUtils.DEFAULT_DATE_TIME_FORMAT);
		boolean vEnd = DateTimeUtils.dateCompare(end, receiveTimestamp, DateTimeUtils.DEFAULT_DATE_TIME_FORMAT);

		if (vBegin && vEnd) {
			return true;
		}

		return false;
	}
}
